<?php

namespace App\Service\OpenShop\SiteLocation;

use App\Enums\OpenShop\FeishuMini\ProgrammingEnum;
use App\Enums\OpenShop\FeishuMini\SandTableEnum;
use App\Enums\OpenShop\InvestmentPromotion\SignOrderEnum;
use App\Library\Rms\RmsUserApi;
use App\Models\Common\ConfigModel;
use App\Models\Common\OperateLogModel;
use App\Models\Common\ResourcesModel;
use App\Models\Guanyuan\GuanyuanSyncShopListModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopAddressModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopOrganizationManageModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopUserBaseInfoModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationModel;
use App\Models\Wanggui\BusinessAoiModel;
use App\Models\Wanggui\SandTablePolymerizeDotInfoModel;
use App\Service\BaseService;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Kuafu\File\FileUtil;
use League\Geotools\Coordinate\Coordinate;
use League\Geotools\Polygon\Polygon;

class BusinessCircleService extends BaseService
{
    /**
     * @throws \Exception
     */
    public static function addRecordToBusinessCircle($id, $files, $record, $userId, $username)
    {
        $businessAoiModel = BusinessAoiModel::query()
            ->where('id', $id)
            ->first();

        if (null == $businessAoiModel) {
            self::throwErr('商圈不存在');
        }

        $businessAoiModel->updatedByUid = $userId;
        $businessAoiModel->save();

        // 添加记录
        $model = OperateLogModel::add(
            OperateLogModel::BUSINESS_BUSINESS_CIRCLE_RECORD,
            $id,
            $id,
            '添加记录',
            $record,
            OperateLogModel::STATUS_OK,
            $userId,
            $username,
        );

        // 添加图片
        ResourcesModel::moduleBusinessSingleResourcesUpdate(
            ResourcesModel::MODULE_TYPE_BUSINESS_CIRCLE_RECORD,
            ResourcesModel::BUSINESS_BUSINESS_CIRCLE_RECORD,
            'businessCircleRecord',
            $model->id,
            $files,
        );

    }

    public static function addPreOccupyToBusinessCircle($id, string $username, string $mobile, $rmsUserId, $rmsUsername)
    {
        $businessAoiModel = BusinessAoiModel::query()
            ->where('id', $id)
            ->first();

        if (null == $businessAoiModel) {
            self::throwErr('商圈不存在');
        }

        $oldPreOccupyUsername = $businessAoiModel->preOccupyUsername;
        $oldPreOccupyMobile   = $businessAoiModel->preOccupyMobile;

        if ($oldPreOccupyMobile == $mobile) {
            return;
        }

        $businessAoiModel->preOccupyUsername = $username;
        $businessAoiModel->preOccupyMobile   = $mobile;
        $businessAoiModel->updatedByUid      = $rmsUserId;
        $businessAoiModel->occupyStatus      = strlen($mobile) ? BusinessAoiModel::OCCUPY_ON : BusinessAoiModel::OCCUPY_OFF;
        $businessAoiModel->save();


        if (strlen($oldPreOccupyMobile) == 0 && strlen($mobile)) {
            $logName    = '添加加盟商';
            $logContent = "商圈占用状态，修改为已占用；添加占位加盟商，{$username} {$mobile}";
        } elseif (strlen($oldPreOccupyMobile) && strlen($mobile)) {
            $logName    = '修改加盟商';
            $logContent = "占位加盟商{$oldPreOccupyUsername} {$oldPreOccupyMobile} 修改为 {$username} {$mobile}";
        } elseif (strlen($oldPreOccupyMobile) && strlen($mobile) == 0) {
            $logName    = '移除加盟商';
            $logContent = "商圈占用状态，修改为未占用；移出占位加盟商，{$oldPreOccupyUsername} {$oldPreOccupyMobile}";
        } elseif (strlen($oldPreOccupyMobile) == 0 && strlen($mobile) == 0) {
            return;
        } else {
            self::throwErr('加盟商占位操作失败');
        }


        // 添加记录
        OperateLogModel::add(
            OperateLogModel::BUSINESS_BUSINESS_CIRCLE_RECORD,
            $id,
            $id,
            $logName,
            $logContent,
            OperateLogModel::STATUS_OK,
            $rmsUserId,
            $rmsUsername,
        );
    }

    /**
     * 删除商圈记录
     * @param $id
     * @return void
     */
    public static function deleteRecordToBusinessCircle($id)
    {
        $operateLogModel = OperateLogModel::query()
            ->where('id', $id)
            ->first();

        if (null != $operateLogModel && $operateLogModel->business != OperateLogModel::BUSINESS_BUSINESS_CIRCLE_RECORD) {
            self::throwErr('商圈记录不存在');
        }

        $operateLogModel->isDeleted = 1;
        $operateLogModel->save();
    }


    /**
     * 获得加盟商列表
     * @param $id
     * @param $name
     * @param $pageNum
     * @param $pageSize
     * @return array
     */
    public static function franchiseeList($id, $name, $cityCode, $pageNum, $pageSize): array
    {
        // 获得所有加盟商
        $list = Cache::remember('businessCircle:franchiseeList:' . $cityCode, 87400, function () use ($cityCode) {
            $list = [];
            OpenShopSignOrderModel::query()
                ->where('shopCode', '<', OpenShopSignOrderModel::SHOP_CODE_TEST)
                ->whereIn('orderNo', function ($query) use ($cityCode) {
                    $query->select('orderNo')
                        ->from((new OpenShopAddressModel())->getTable())
                        ->where('cityCode', $cityCode)
                        ->orWhere('provinceCode', $cityCode);
                })
                ->whereIn('status', [SignOrderEnum::ORDER_STATUS_OK, SignOrderEnum::ORDER_STATUS_COMPLETE])
                ->orderByDesc('id')
                ->with(['baseInfoRel', 'identityCardRel'])
                ->chunk(50, function ($signOrders) use (&$list) {
                    foreach ($signOrders as $signOrder) {
                        if ($signOrder->shopCode == 0) {
                            continue;
                        }

                        if (!optional($signOrder->baseInfoRel)->mobile) {
                            continue;
                        }

                        if (!optional($signOrder->identityCardRel)->name) {
                            continue;
                        }

                        $list[$signOrder->baseInfoRel->mobile]['username'] = $signOrder->identityCardRel->name;
                        $list[$signOrder->baseInfoRel->mobile]['mobile']   = $signOrder->baseInfoRel->mobile;

                        if (!isset($list[$signOrder->baseInfoRel->mobile]['shopCode'])) {
                            $list[$signOrder->baseInfoRel->mobile]['shopCode'] = [$signOrder->shopCode];
                        } else {
                            $list[$signOrder->baseInfoRel->mobile]['shopCode'][] = $signOrder->shopCode;
                        }
                        $list[$signOrder->baseInfoRel->mobile]['shopCode'] = array_values(array_unique($list[$signOrder->baseInfoRel->mobile]['shopCode']));
                    }
                });
            return $list;
        });

        // 获得已有的加盟商
        $choose = [];
        if ($id) {
            $businessAoiModel = BusinessAoiModel::query()
                ->where('id', $id)
                ->select(['preOccupyUsername', 'preOccupyMobile'])
                ->first();

            if ($businessAoiModel->preOccupyUsername && $businessAoiModel->preOccupyMobile) {
                $choose = [
                    'username' => $businessAoiModel->preOccupyUsername,
                    'mobile'   => $businessAoiModel->preOccupyMobile,
                ];
            }
        }

        if (isset($choose['mobile'])) {
            $choose['shopCode'] = collect($list)->where('mobile', $choose['mobile'])->first()['shopCode'] ?? [];
        }

        if (strlen($name)) {
            foreach ($list as $key => $item) {
                if (strrpos($item['username'], $name) === false && strrpos($item['mobile'], $name) === false && !in_array($name, $item['shopCode'])) {
                    unset($list[$key]);
                }
            }
        }

        // 总页数
        $last_page = ceil(count($list) / $pageSize);

        // 分页数据
        $start      = ($pageNum - 1) * $pageSize;
        $paged_data = array_slice(array_values($list), $start, $pageSize);

        // 放在第一页
        if ($pageNum == 1 && !empty($choose)) {
            $paged_data = array_merge([$choose], $paged_data);

            // 去重
            $uniqueData = array_reduce($paged_data, function ($carry, $item) {
                $key         = $item['username'] . '|' . $item['mobile'];
                $carry[$key] = $item;
                return $carry;
            }, []);

            $paged_data = array_values($uniqueData);
        }

        return [
            'count'     => count($list),
            'list'      => $paged_data,
            'totalPage' => $last_page,
            'pageNum'   => $pageNum,
            'pageSize'  => $pageSize,
        ];
    }

    /**
     * 获得商圈详情
     * @param $id
     * @param $rmsUserId
     * @return array
     */
    public static function detail($id, $rmsUserId): array
    {
        $businessAoiModel = BusinessAoiModel::query()
            ->where('id', $id)
            ->first();

        if (null == $businessAoiModel) {
            self::throwErr('商圈不存在');
        }

        $specialCityCodeJson = (string)ConfigModel::query()
            ->where('module', 'businessAoi')
            ->where('name', 'cityCodeConvert')
            ->value('value');
        $specialCityCodeArr  = json_decode($specialCityCodeJson, true);

        $cityCode = [$businessAoiModel->cityCode];

        if (in_array($businessAoiModel->cityCode, $specialCityCodeArr)) {
            if ($businessAoiModel->cityCode == 500000) {
                $cityCode = [500100, 500200];
            } else {
                $cityCode = [array_search($businessAoiModel->cityCode, $specialCityCodeArr)];
            }
        }

        if (empty($cityCode)) {
            self::throwErr('城市code不存在');
        }

        // 通过userId获得username
        $username = (new RmsUserApi())->getUserInfoByIds([$businessAoiModel->updatedByUid], ['username'])['data'][0]['username'] ?? '';

        // 获得所有省总及其附属负责人 & 当前用户
        $managerUserIds = [$rmsUserId];
        OpenShopOrganizationManageModel::query()
            ->select(['operationUid', 'operationAttacheUser'])
            ->each(function (OpenShopOrganizationManageModel $openShopOrganizationManageModel) use (&$managerUserIds) {
                $managerUserIds[]     = $openShopOrganizationManageModel->operationUid;
                $operationAttacheUser = json_decode($openShopOrganizationManageModel->operationAttacheUser, true);
                $managerUserIds       = array_merge($managerUserIds, collect($operationAttacheUser)->pluck('uid')->toArray());
            });

        // 获得商圈内网规点位及其门店列表
        $boundary = collect(json_decode($businessAoiModel->boundary, true))->map(function ($point) {
            return [
                $point['lat'],
                $point['lng'],
            ];
        })->toArray();

        $polygon = new Polygon($boundary);

        $pointInfo = [
            'kfShop'                     => [],
            'mallData'                   => [],
            'streetData'                 => [],
            'communityData'              => [],
            'nationalIndustrialParkData' => [],
            'nationalUniversitiesData'   => [],
        ];

        SandTablePolymerizeDotInfoModel::query()
            ->whereIn('cityCode', $cityCode)
            ->where('businessAoiId', $id)
            ->chunkById(100, function ($points) use ($polygon, &$pointInfo) {
                foreach ($points as $point) {
                    // 经纬度过滤
                    if (!$point->lat || !$point->lng) {
                        continue;
                    }

                    // 判断点是否在区域内
                    $res = $polygon->pointInPolygon(new Coordinate([$point->lat, $point->lng]));

                    if (!$res) {
                        continue;
                    }

                    // 门店
                    if (
                        $point->type == ProgrammingEnum::PC_TYPE_LIST_HEAD_KF
                        &&
                        in_array($point->subType,
                            [
                                ProgrammingEnum::KF_SHOP_SAND_TABLE_KEY_MAPPING[ProgrammingEnum::KF_SHOP_STATUS_CLOSE],
                                ProgrammingEnum::KF_SHOP_SAND_TABLE_KEY_MAPPING[ProgrammingEnum::KF_SHOP_STATUS_BUSINESS],
                                ProgrammingEnum::KF_SHOP_SAND_TABLE_KEY_MAPPING[ProgrammingEnum::KF_SHOP_STATUS_STOP],
                                ProgrammingEnum::KF_SHOP_SAND_TABLE_KEY_MAPPING[ProgrammingEnum::KF_SHOP_STATUS_PREPARE]
                            ])) {
                        $pointInfo['kfShop'][] = [
                            'status'  => $status = (ProgrammingEnum::KF_SHOP_STATUS_SELECT_MAPPING[array_search($point->subType, ProgrammingEnum::KF_SHOP_SAND_TABLE_KEY_MAPPING)] ?? ''),
                            'name'    => $status . '·' . $point->name,
                            'type'    => ProgrammingEnum::PC_TYPE_LIST_HEAD_KF,
                            'subType' => $point->subType,
                            'id'      => $point->relationId,
                            'lat'     => $point->lat,
                            'lng'     => $point->lng,
                        ];
                    }

                    if ($point->grade == 0) {
                        continue;
                    }

                    // 商场
                    if ($point->type == 'mallProgramming') {
                        $pointInfo['mallData'][] = [
                            'name'  => $point->name,
                            'sort'  => $point->grade,
                            'grade' => ProgrammingEnum::PC_GRADE_MAPPING[$point->grade] ?? '-',
                            'type'  => 'mallProgramming',
                            'id'    => $point->relationId,
                            'lat'   => $point->lat,
                            'lng'   => $point->lng,
                        ];
                    }

                    // 街道
                    if ($point->type == 'streetProgramming') {
                        $pointInfo['streetData'][] = [
                            'name'  => $point->name,
                            'sort'  => $point->grade,
                            'grade' => ProgrammingEnum::PC_GRADE_MAPPING[$point->grade] ?? '-',
                            'type'  => 'streetProgramming',
                            'id'    => $point->relationId,
                            'lat'   => $point->lat,
                            'lng'   => $point->lng,
                        ];
                    }

                    // 社区
                    if ($point->type == 'communityProgramming') {
                        $pointInfo['communityData'][] = [
                            'name'  => $point->name,
                            'sort'  => $point->grade,
                            'grade' => ProgrammingEnum::PC_GRADE_MAPPING[$point->grade] ?? '-',
                            'type'  => 'communityProgramming',
                            'id'    => $point->relationId,
                            'lat'   => $point->lat,
                            'lng'   => $point->lng,
                        ];
                    }

                    // 产业园
                    if ($point->type == 'parkProgramming') {
                        $pointInfo['nationalIndustrialParkData'][] = [
                            'name'  => $point->name,
                            'sort'  => $point->grade,
                            'grade' => ProgrammingEnum::PC_GRADE_MAPPING[$point->grade] ?? '-',
                            'type'  => 'parkProgramming',
                            'id'    => $point->relationId,
                            'lat'   => $point->lat,
                            'lng'   => $point->lng,
                        ];
                    }

                    // 大学
                    if ($point->type == 'schoolProgramming') {
                        $pointInfo['nationalUniversitiesData'][] = [
                            'name'  => $point->name,
                            'sort'  => $point->grade,
                            'grade' => ProgrammingEnum::PC_GRADE_MAPPING[$point->grade] ?? '-',
                            'type'  => 'schoolProgramming',
                            'id'    => $point->relationId,
                            'lat'   => $point->lat,
                            'lng'   => $point->lng,
                        ];
                    }
                }
            });
        // 根据手机号获得未落址门店
        $noSettlementShopCodes = [];
        if (strlen($businessAoiModel->preOccupyMobile)) {
            $mobile = $businessAoiModel->preOccupyMobile;
            OpenShopSiteLocationModel::query()
                ->where('source', OpenShopSiteLocationModel::SOURCE_OPEN_SHOP)
                ->where(function ($query) use ($mobile) {
                    $query->whereIn('orderNo', function ($subQuery) use ($mobile) {
                        $subQuery->select('orderNo')
                            ->from((new OpenShopUserBaseInfoModel())->getTable())
                            ->where('mobile', $mobile);
                    });
                })
                ->whereIn('siteStatus', [
                    OpenShopSiteLocationModel::SITE_STATUS_0,
                    OpenShopSiteLocationModel::SITE_STATUS_1,
                    OpenShopSiteLocationModel::SITE_STATUS_2,
                    OpenShopSiteLocationModel::SITE_STATUS_3,
                    OpenShopSiteLocationModel::SITE_STATUS_4,
                    OpenShopSiteLocationModel::SITE_STATUS_11,
                    OpenShopSiteLocationModel::SITE_STATUS_10,
                    OpenShopSiteLocationModel::SITE_STATUS_20,
                ])
                ->with(['signOrderRel'])
                ->select(['orderNo', 'source', 'siteStatus'])
                ->get()
                ->each(function (OpenShopSiteLocationModel $openShopSiteLocationModel) use (&$noSettlementShopCodes) {
                    if (null == $openShopSiteLocationModel->signOrderRel) {
                        return null;
                    }

                    if (!$openShopSiteLocationModel->signOrderRel->shopCode || $openShopSiteLocationModel->signOrderRel->shopCode > OpenShopSignOrderModel::SHOP_CODE_TEST) {
                        return null;
                    }

                    if (!in_array($openShopSiteLocationModel->signOrderRel->status, [SignOrderEnum::ORDER_STATUS_OK, SignOrderEnum::ORDER_STATUS_COMPLETE])) {
                        return null;
                    }

                    $noSettlementShopCodes[] = $openShopSiteLocationModel->signOrderRel->shopCode;
                });
        }


        // 记录
        $recordModel = OperateLogModel::query()
            ->where('module', '')
            ->where('business', OperateLogModel::BUSINESS_BUSINESS_CIRCLE_RECORD)
            ->where('businessId', $businessAoiModel->id)
            ->with(['resourcesBusinessCircleRel'])
            ->orderByDesc('id')
            ->get()
            ->map(function (OperateLogModel $operateLogModel) use ($managerUserIds) {

                // 获得记录文件
                $files = [];
                if ($operateLogModel->resourcesBusinessCircleRel->count()) {
                    foreach ($operateLogModel->resourcesBusinessCircleRel as $resource) {
                        $files[] = FileUtil::domain() . '/' . $resource->url;
                    }
                }

                return [
                    'files'       => $files,
                    'username'    => $operateLogModel->userName,
                    'createdAt'   => $operateLogModel->createdAt->toDateTimeString(),
                    'cover'       => SandTableEnum::DEFAULT_KUAFU_LOGO,
                    'content'     => $operateLogModel->logContent,
                    'deletePower' => in_array($operateLogModel->createdByUid, $managerUserIds) && $operateLogModel->logName == '添加记录',
                    'id'          => $operateLogModel->id,
                ];
            })->toArray();

        return [
            'id'                 => $businessAoiModel->id,
            'name'               => $businessAoiModel->name,
            'occupyStatus'       => $businessAoiModel->occupyStatus,
            'occupyStatusText'   => $businessAoiModel->occupyStatusText,
            'province'           => $businessAoiModel->province,
            'city'               => $businessAoiModel->city,
            'district'           => $businessAoiModel->district,
            'lng'                => $businessAoiModel->lng,
            'lat'                => $businessAoiModel->lat,
            'cityCode'           => $businessAoiModel->cityCode,
            'updatedUsername'    => $username,
            'updatedAt'          => $businessAoiModel->updatedAt->toDateTimeString(),
            'capacity'           => $businessAoiModel->capacity,
            'openShopCount'      => $normalShopCount = collect($pointInfo['kfShop'])->where('subType', '!=', 'closeKfShop')->count(),  // 过滤掉闭店的
            'shopPermeationRate' => $businessAoiModel->capacity > 0 ? (round($normalShopCount / $businessAoiModel->capacity, 4) * 100 . '%') : '-',
            'population'         => $businessAoiModel->population,
            'worth'              => $businessAoiModel->worth,
            'cityWorth'          => $businessAoiModel->cityWorth,
            'franchisee'         => [
                'username'              => $businessAoiModel->preOccupyUsername,
                'mobile'                => $businessAoiModel->preOccupyMobile,
                'noSettlementShopCodes' => array_values(array_unique($noSettlementShopCodes)),
            ],
            'pointInfo'          => $pointInfo,
            'records'            => $recordModel
        ];
    }

}